home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume22 / nn6.4 / part06 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  54.4 KB

  1. Subject:  v22i041:  NN Newsreader, release 6.4, Part06/21
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 424bcc2d 36950156 9e5dda93 f728ae0b
  5.  
  6. Submitted-by: "Kim F. Storm" <storm@texas.dk>
  7. Posting-number: Volume 22, Issue 41
  8. Archive-name: nn6.4/part06
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  conf/s-hpux.h keymap.c menu.c
  17. # Wrapped by storm@texas.dk on Sun May  6 18:19:28 1990
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. echo If this archive is complete, you will see the following message:
  20. echo '          "shar: End of archive 6 (of 22)."'
  21. if test -f 'conf/s-hpux.h' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'conf/s-hpux.h'\"
  23. else
  24.   echo shar: Extracting \"'conf/s-hpux.h'\" \(510 characters\)
  25.   sed "s/^X//" >'conf/s-hpux.h' <<'END_OF_FILE'
  26. X/*
  27. X *    This version is for Hewlett-Packard HP-UX
  28. X */
  29. X
  30. X#define NO_DIRENT_H
  31. X#include "s-sys5.h"
  32. X
  33. X#undef    SIGNAL_HANDLERS_ARE_VOID    /* */
  34. X
  35. X/*
  36. X *    Define if your system provides the "directory(3X)" access routines
  37. X *
  38. X *    If true, include the header file(s) required by the package below
  39. X *    (remember that <sys/types.h> or equivalent is included above)
  40. X *    Also typedef Direntry to the proper struct type.
  41. X */
  42. X
  43. X#define    HAVE_DIRECTORY            /* */
  44. X
  45. X#include <ndir.h>            /* HP-UX */
  46. X
  47. Xtypedef struct direct Direntry;        /* HP-UX */
  48. END_OF_FILE
  49.   if test 510 -ne `wc -c <'conf/s-hpux.h'`; then
  50.     echo shar: \"'conf/s-hpux.h'\" unpacked with wrong size!
  51.   fi
  52.   # end of 'conf/s-hpux.h'
  53. fi
  54. if test -f 'keymap.c' -a "${1}" != "-c" ; then 
  55.   echo shar: Will not clobber existing file \"'keymap.c'\"
  56. else
  57.   echo shar: Extracting \"'keymap.c'\" \(17311 characters\)
  58.   sed "s/^X//" >'keymap.c' <<'END_OF_FILE'
  59. X/*
  60. X *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  61. X *
  62. X *    Keyboard (re)mapping
  63. X */
  64. X
  65. X#include "config.h"
  66. X#include "keymap.h"
  67. X#include "term.h"
  68. X
  69. X
  70. X/*
  71. X * standard keyboard mapping for more()
  72. X *
  73. X *    redraw            ^L, ^R
  74. X *    continue        space
  75. X *    repeat message        ^P
  76. X *    help            ?
  77. X *    shell escape        !
  78. X *    version            V
  79. X *    extended command    :
  80. X *    quit            Q
  81. X *
  82. X *    save            S, O
  83. X *    save, no header        W
  84. X *    reply            R
  85. X *    follow up        F
  86. X *    mail (forward)        M
  87. X *    cancel            C
  88. X *    unsubscribe        U
  89. X *    group overview        Y
  90. X *    print article        P
  91. X *    kill handling        K
  92. X *
  93. X *    update, goto next group    X
  94. X *    no update, next group    q, Z
  95. X *    return to menu        =
  96. X *    prev article        p
  97. X *    goto group        G
  98. X *
  99. X *    line forward        CR/NL
  100. X *    half page forward    d/^D
  101. X *    half page back        u/^U
  102. X *    full page back        BS, DEL, (up arrow)
  103. X *    goto line        g
  104. X *    goto match        /
  105. X *    next match        .
  106. X *
  107. X *    select subject        N, *
  108. X *
  109. X *    header            h
  110. X *    digest header        H
  111. X *    top            t
  112. X *    last page        $
  113. X *    leave article        l
  114. X *    leave article to next    L
  115. X *    next article        n
  116. X *    kill subject        k
  117. X *
  118. X *    rot13            D
  119. X *    compress        c
  120. X */
  121. X
  122. Xexport int more_key_map[KEY_MAP_SIZE] = {
  123. X
  124. X/* NUL ^@ */    K_UNBOUND,
  125. X/* SOH ^A */    K_UNBOUND,
  126. X/* STX ^B */    K_UNBOUND,
  127. X/* ETX ^C */    K_UNBOUND,
  128. X/* EOT ^D */        K_NEXT_HALF_PAGE,
  129. X/* ENQ ^E */    K_UNBOUND,
  130. X/* ACK ^F */    K_UNBOUND,
  131. X/* BEL ^G */        K_INVALID,
  132. X/* BS  ^H */        K_PREV_PAGE,
  133. X/* TAB ^I */        K_SKIP_LINES,
  134. X/* NL  ^J */        K_NEXT_LINE,
  135. X/* VT  ^K */    K_UNBOUND,
  136. X/* FF  ^L */        K_REDRAW,
  137. X/* CR  ^M */        K_NEXT_LINE,
  138. X/* SO  ^N */    K_UNBOUND,
  139. X/* SI  ^O */    K_UNBOUND,
  140. X/* DLE ^P */        K_LAST_MESSAGE,
  141. X/* DC1 ^Q */    K_UNBOUND,
  142. X/* DC2 ^R */        K_REDRAW,
  143. X/* DC3 ^S */    K_UNBOUND,
  144. X/* DC4 ^T */    K_UNBOUND,
  145. X/* NAK ^U */        K_PREV_HALF_PAGE,
  146. X/* SYN ^V */        K_NEXT_PAGE,
  147. X/* ETB ^W */    K_UNBOUND,
  148. X/* CAN ^X */    K_UNBOUND,
  149. X/* EM  ^Y */    K_UNBOUND,
  150. X/* SUB ^Z */    K_UNBOUND,
  151. X/* ESC ^[ */    K_UNBOUND,
  152. X/* FS  ^\ */    K_UNBOUND,
  153. X/* GS  ^] */    K_UNBOUND,
  154. X/* RS  ^^ */    K_UNBOUND,
  155. X/* US  ^_ */    K_UNBOUND,
  156. X/* SP  */        K_CONTINUE,
  157. X/* !   */        K_SHELL,
  158. X/* "   */    K_UNBOUND,
  159. X/* #   */    K_UNBOUND,
  160. X/* $   */        K_LAST_PAGE,
  161. X/* %   */        K_PREVIEW,
  162. X/* &   */    K_UNBOUND,
  163. X/* '   */    K_UNBOUND,
  164. X/* (   */    K_UNBOUND,
  165. X/* )   */    K_UNBOUND,
  166. X/* *   */        K_SELECT_SUBJECT,
  167. X/* +   */    K_UNBOUND,
  168. X/* ,   */    K_UNBOUND,
  169. X/* -   */    K_UNBOUND,
  170. X/* .   */        K_NEXT_MATCH,
  171. X/* /   */        K_GOTO_MATCH,
  172. X/* 0   */    K_UNBOUND,
  173. X/* 1   */    K_UNBOUND,
  174. X/* 2   */    K_UNBOUND,
  175. X/* 3   */    K_UNBOUND,
  176. X/* 4   */    K_UNBOUND,
  177. X/* 5   */    K_UNBOUND,
  178. X/* 6   */    K_UNBOUND,
  179. X/* 7   */    K_UNBOUND,
  180. X/* 8   */    K_UNBOUND,
  181. X/* 9   */    K_UNBOUND,
  182. X/* :   */         K_EXTENDED_CMD,
  183. X/* ;   */    K_UNBOUND,
  184. X/* <   */    K_UNBOUND,
  185. X/* =   */        K_BACK_TO_MENU,
  186. X/* >   */    K_UNBOUND,
  187. X/* ?   */        K_HELP,
  188. X/* @   */    K_UNBOUND,
  189. X/* A   */    K_UNBOUND,
  190. X/* B   */    K_UNBOUND,
  191. X/* C   */        K_CANCEL,
  192. X/* D   */        K_ROT13,
  193. X/* E   */    K_UNBOUND,
  194. X/* F   */        K_FOLLOW_UP,
  195. X/* G   */        K_GOTO_GROUP,
  196. X/* H   */        K_FULL_DIGEST,
  197. X/* I   */    K_UNBOUND,
  198. X/* J   */    K_UNBOUND,
  199. X/* K   */        K_KILL_HANDLING,
  200. X/* L   */        K_LEAVE_NEXT,
  201. X/* M   */        K_MAIL_OR_FORWARD,
  202. X/* N   */        K_NEXT_GROUP_NO_UPDATE,
  203. X/* O   */        K_SAVE_SHORT_HEADER,
  204. X/* P   */        K_PRINT,
  205. X/* Q   */         K_QUIT,
  206. X/* R   */        K_REPLY,
  207. X/* S   */        K_SAVE_FULL_HEADER,
  208. X/* T   */    K_UNBOUND,
  209. X/* U   */        K_UNSUBSCRIBE,
  210. X/* V   */         K_VERSION,
  211. X/* W   */        K_SAVE_NO_HEADER,
  212. X/* X   */        K_READ_GROUP_UPDATE,
  213. X/* Y   */        K_GROUP_OVERVIEW,
  214. X/* Z   */        K_BACK_TO_MENU,
  215. X/* [   */    K_UNBOUND,
  216. X/* \   */    K_UNBOUND,
  217. X/* ]   */    K_UNBOUND,
  218. X/* ^   */        K_FIRST_PAGE,
  219. X/* _   */    K_UNBOUND,
  220. X/* `   */    K_UNBOUND,
  221. X/* a   */        K_FORW_ARTICLE,
  222. X/* b   */        K_BACK_ARTICLE,
  223. X/* c   */        K_COMPRESS,
  224. X/* d   */        K_NEXT_HALF_PAGE,
  225. X/* e   */    K_UNBOUND,
  226. X/* f   */        K_FOLLOW_UP,
  227. X/* g   */        K_GOTO_LINE,
  228. X/* h   */        K_HEADER_PAGE,
  229. X/* i   */    K_UNBOUND,
  230. X/* j   */    K_UNBOUND,
  231. X/* k   */        K_NEXT_SUBJECT,
  232. X/* l   */        K_LEAVE_ARTICLE,
  233. X/* m   */        K_MAIL_OR_FORWARD,
  234. X/* n   */        K_NEXT_ARTICLE,
  235. X/* o   */        K_SAVE_SHORT_HEADER,
  236. X/* p   */        K_PREVIOUS /* article */,
  237. X/* q   */        K_NEXT_GROUP_NO_UPDATE,
  238. X/* r   */        K_REPLY,
  239. X/* s   */        K_SAVE_FULL_HEADER,
  240. X/* t   */        K_FIRST_PAGE,
  241. X/* u   */        K_PREV_HALF_PAGE,
  242. X/* v   */    K_UNBOUND,
  243. X/* w   */        K_SAVE_NO_HEADER,
  244. X/* x   */    K_UNBOUND,
  245. X/* y   */    K_UNBOUND,
  246. X/* z   */    K_UNBOUND,
  247. X/* {   */    K_UNBOUND,
  248. X/* |   */    K_UNBOUND,
  249. X/* }   */    K_UNBOUND,
  250. X/* ~   */    K_UNBOUND,
  251. X/* DEL */        K_PREV_PAGE,
  252. X/* 200 */    K_UNBOUND,
  253. X/* up  */        K_PREV_PAGE,
  254. X/* down */        K_NEXT_PAGE,
  255. X/* left */    K_UNBOUND,
  256. X/* right */    K_UNBOUND,
  257. X/* #0  */    K_UNBOUND,
  258. X/* #1  */    K_UNBOUND,
  259. X/* #2  */    K_UNBOUND,
  260. X/* #3  */    K_UNBOUND,
  261. X/* #4  */    K_UNBOUND,
  262. X/* #5  */    K_UNBOUND,
  263. X/* #6  */    K_UNBOUND,
  264. X/* #7  */    K_UNBOUND,
  265. X/* #8  */    K_UNBOUND,
  266. X/* #9  */    K_UNBOUND
  267. X};
  268. X
  269. X
  270. X
  271. X/*
  272. X * standard keyboard mappings for menu()
  273. X *
  274. X *    illegal command
  275. X *    redraw            ^L, ^R
  276. X *    continue        space
  277. X *    continue no mark    return, newline
  278. X *    repeat message        ^P
  279. X *    help            ?
  280. X *    shell escape        !
  281. X *    version            V
  282. X *    alternative commands    :
  283. X *    quit            Q
  284. X *
  285. X *    save            S, O
  286. X *    save, no header        W
  287. X *    reply            R
  288. X *    follow up        F
  289. X *    mail (forward)        M
  290. X *    cancel            C
  291. X *    unsubscribe        U
  292. X *    group overview        Y
  293. X *    kill handling        K
  294. X *    junk articles        J
  295. X *
  296. X *    read, then next        X
  297. X *    read, then same        Z
  298. X *    no update, next        N
  299. X *    prev group        P
  300. X *    goto group        G
  301. X *    advance group        A
  302. X *    back group        B
  303. X *
  304. X *    article identifier    a-z 0-9
  305. X *    inverse            @
  306. X *    select current, next    .
  307. X *    next            , (down arrow)
  308. X *    prev            / (up arrow)
  309. X *    select subject        *
  310. X *    range            -
  311. X *    auto select         +
  312. X *
  313. X *    next page        >
  314. X *    prev page        <
  315. X *    first page        ^
  316. X *    last page        $
  317. X *
  318. X *    pre-view article    %
  319. X *
  320. X *    layout            L
  321. X */
  322. X
  323. X
  324. Xexport int menu_key_map[KEY_MAP_SIZE] = {
  325. X
  326. X/* NUL ^@ */    K_UNBOUND,
  327. X/* SOH ^A */    K_UNBOUND,
  328. X/* STX ^B */    K_UNBOUND,
  329. X/* ETX ^C */    K_UNBOUND,
  330. X/* EOT ^D */    K_UNBOUND,
  331. X/* ENQ ^E */    K_UNBOUND,
  332. X/* ACK ^F */    K_UNBOUND,
  333. X/* BEL ^G */        K_INVALID,
  334. X/* BS  ^H */        K_PREV_LINE,
  335. X/* TAB ^I */    K_UNBOUND,
  336. X/* NL  ^J */        K_CONTINUE_NO_MARK,
  337. X/* VT  ^K */    K_UNBOUND,
  338. X/* FF  ^L */        K_REDRAW,
  339. X/* CR  ^M */        K_CONTINUE_NO_MARK,
  340. X/* SO  ^N */    K_UNBOUND,
  341. X/* SI  ^O */    K_UNBOUND,
  342. X/* DLE ^P */        K_LAST_MESSAGE,
  343. X/* DC1 ^Q */    K_UNBOUND,
  344. X/* DC2 ^R */        K_REDRAW,
  345. X/* DC3 ^S */    K_UNBOUND,
  346. X/* DC4 ^T */    K_UNBOUND,
  347. X/* NAK ^U */    K_UNBOUND,
  348. X/* SYN ^V */        K_NEXT_PAGE,
  349. X/* ETB ^W */    K_UNBOUND,
  350. X/* CAN ^X */    K_UNBOUND,
  351. X/* EM  ^Y */    K_UNBOUND,
  352. X/* SUB ^Z */    K_UNBOUND,
  353. X/* ESC ^[ */    K_UNBOUND,
  354. X/* FS  ^\ */    K_UNBOUND,
  355. X/* GS  ^] */    K_UNBOUND,
  356. X/* RS  ^^ */    K_UNBOUND,
  357. X/* US  ^_ */    K_UNBOUND,
  358. X/* SP  */        K_CONTINUE,
  359. X/* !   */        K_SHELL,
  360. X/* "   */        K_LAYOUT,
  361. X/* #   */    K_UNBOUND,
  362. X/* $   */        K_LAST_PAGE,
  363. X/* %   */        K_PREVIEW,
  364. X/* &   */    K_UNBOUND,
  365. X/* '   */    K_UNBOUND,
  366. X/* (   */    K_UNBOUND,
  367. X/* )   */    K_UNBOUND,
  368. X/* *   */        K_SELECT_SUBJECT,
  369. X/* +   */        K_AUTO_SELECT,
  370. X/* ,   */        K_NEXT_LINE,
  371. X/* -   */        K_SELECT_RANGE,
  372. X/* .   */        K_SELECT,
  373. X/* /   */        K_PREV_LINE,
  374. X/* 0   */    K_ARTICLE_ID + 26,
  375. X/* 1   */    K_ARTICLE_ID + 27,
  376. X/* 2   */    K_ARTICLE_ID + 28,
  377. X/* 3   */    K_ARTICLE_ID + 29,
  378. X/* 4   */    K_ARTICLE_ID + 30,
  379. X/* 5   */    K_ARTICLE_ID + 31,
  380. X/* 6   */    K_ARTICLE_ID + 32,
  381. X/* 7   */    K_ARTICLE_ID + 33,
  382. X/* 8   */    K_ARTICLE_ID + 34,
  383. X/* 9   */    K_ARTICLE_ID + 35,
  384. X/* :   */        K_EXTENDED_CMD,
  385. X/* ;   */    K_UNBOUND,
  386. X/* <   */        K_PREV_PAGE,
  387. X/* =   */        K_GOTO_MATCH,
  388. X/* >   */        K_NEXT_PAGE,
  389. X/* ?   */        K_HELP,
  390. X/* @   */        K_SELECT_INVERT,
  391. X/* A   */        K_ADVANCE_GROUP,
  392. X/* B   */        K_BACK_GROUP,
  393. X/* C   */        K_CANCEL,
  394. X/* D   */    K_UNBOUND,
  395. X/* E   */    K_UNBOUND,
  396. X/* F   */        K_FOLLOW_UP,
  397. X/* G   */        K_GOTO_GROUP,
  398. X/* H   */    K_UNBOUND,
  399. X/* I   */    K_UNBOUND,
  400. X/* J   */        K_JUNK_ARTICLES,
  401. X/* K   */        K_KILL_HANDLING,
  402. X/* L   */        K_LEAVE_NEXT,
  403. X/* M   */        K_MAIL_OR_FORWARD,
  404. X/* N   */        K_NEXT_GROUP_NO_UPDATE,
  405. X/* O   */        K_SAVE_SHORT_HEADER,
  406. X/* P   */        K_PREVIOUS /* group */,
  407. X/* Q   */        K_QUIT,
  408. X/* R   */        K_REPLY,
  409. X/* S   */        K_SAVE_FULL_HEADER,
  410. X/* T   */    K_UNBOUND,
  411. X/* U   */        K_UNSUBSCRIBE,
  412. X/* V   */        K_VERSION,
  413. X/* W   */        K_SAVE_NO_HEADER,
  414. X/* X   */        K_READ_GROUP_UPDATE,
  415. X/* Y   */        K_GROUP_OVERVIEW,
  416. X/* Z   */        K_READ_GROUP_THEN_SAME,
  417. X/* [   */    K_UNBOUND,
  418. X/* \   */    K_UNBOUND,
  419. X/* ]   */    K_UNBOUND,
  420. X/* ^   */        K_FIRST_PAGE,
  421. X/* _   */    K_UNBOUND,
  422. X/* `   */    K_UNBOUND,
  423. X/* a   */    K_ARTICLE_ID +  0,
  424. X/* b   */    K_ARTICLE_ID +  1,
  425. X/* c   */    K_ARTICLE_ID +  2,
  426. X/* d   */    K_ARTICLE_ID +  3,
  427. X/* e   */    K_ARTICLE_ID +  4,
  428. X/* f   */    K_ARTICLE_ID +  5,
  429. X/* g   */    K_ARTICLE_ID +  6,
  430. X/* h   */    K_ARTICLE_ID +  7,
  431. X/* i   */    K_ARTICLE_ID +  8,
  432. X/* j   */    K_ARTICLE_ID +  9,
  433. X/* k   */    K_ARTICLE_ID + 10,
  434. X/* l   */    K_ARTICLE_ID + 11,
  435. X/* m   */    K_ARTICLE_ID + 12,
  436. X/* n   */    K_ARTICLE_ID + 13,
  437. X/* o   */    K_ARTICLE_ID + 14,
  438. X/* p   */    K_ARTICLE_ID + 15,
  439. X/* q   */    K_ARTICLE_ID + 16,
  440. X/* r   */    K_ARTICLE_ID + 17,
  441. X/* s   */    K_ARTICLE_ID + 18,
  442. X/* t   */    K_ARTICLE_ID + 19,
  443. X/* u   */    K_ARTICLE_ID + 20,
  444. X/* v   */    K_ARTICLE_ID + 21,
  445. X/* w   */    K_ARTICLE_ID + 22,
  446. X/* x   */    K_ARTICLE_ID + 23,
  447. X/* y   */    K_ARTICLE_ID + 24,
  448. X/* z   */    K_ARTICLE_ID + 25,
  449. X/* {   */    K_UNBOUND,
  450. X/* |   */    K_UNBOUND,
  451. X/* }   */    K_UNBOUND,
  452. X/* ~   */        K_UNSELECT_ALL,
  453. X/* DEL */        K_PREV_LINE,
  454. X/* 200 */    K_UNBOUND,
  455. X/* up  */        K_PREV_LINE,
  456. X/* down */        K_NEXT_LINE,
  457. X/* left */    K_UNBOUND,
  458. X/* right */    K_UNBOUND,
  459. X/* #0  */    K_UNBOUND,
  460. X/* #1  */    K_UNBOUND,
  461. X/* #2  */    K_UNBOUND,
  462. X/* #3  */    K_UNBOUND,
  463. X/* #4  */    K_UNBOUND,
  464. X/* #5  */    K_UNBOUND,
  465. X/* #6  */    K_UNBOUND,
  466. X/* #7  */    K_UNBOUND,
  467. X/* #8  */    K_UNBOUND,
  468. X/* #9  */    K_UNBOUND
  469. X};
  470. X
  471. X
  472. X
  473. Xstatic struct command_name_map {
  474. X    char *    cmd_name;
  475. X    int       cmd_code;
  476. X    int          cmd_restriction;
  477. X} command_name_map[] = {
  478. X
  479. X    "advance-article",        K_FORW_ARTICLE,        K_ONLY_MORE,
  480. X    "advance-group",        K_ADVANCE_GROUP,    0,
  481. X    "article",            K_ARTICLE_ID,        K_ONLY_MENU,
  482. X    "as",            K_EQUAL_KEY,        0,
  483. X
  484. X    "back-article",        K_BACK_ARTICLE,        K_ONLY_MORE,
  485. X    "back-group",        K_BACK_GROUP,        0,
  486. X
  487. X    "cancel",            K_CANCEL,        0,
  488. X    "command",            K_EXTENDED_CMD,        0,
  489. X    "compress",            K_COMPRESS,        K_ONLY_MORE,
  490. X    "continue",            K_CONTINUE,        0,
  491. X    "continue-no-mark",        K_CONTINUE_NO_MARK,    K_ONLY_MENU,
  492. X
  493. X    "decode",            K_UUDECODE,        0,
  494. X
  495. X    "find",            K_GOTO_MATCH,        0,
  496. X    "find-next",        K_NEXT_MATCH,        K_ONLY_MORE,
  497. X    "follow",            K_FOLLOW_UP,        0,
  498. X    "full-digest",        K_FULL_DIGEST,        K_ONLY_MORE,
  499. X
  500. X    "goto-group",        K_GOTO_GROUP,        0,
  501. X    "goto-menu",        K_BACK_TO_MENU,        K_ONLY_MORE,
  502. X
  503. X    "help",            K_HELP,            0,
  504. X
  505. X    "junk-articles",        K_JUNK_ARTICLES,    K_ONLY_MENU,
  506. X
  507. X    "kill-select",        K_KILL_HANDLING,    0,
  508. X
  509. X    "layout",            K_LAYOUT,        K_ONLY_MENU,
  510. X    "leave-article",        K_LEAVE_ARTICLE,    K_ONLY_MORE,
  511. X    "leave-next",        K_LEAVE_NEXT,        K_ONLY_MORE,
  512. X    "line+1",            K_NEXT_LINE,        0,
  513. X    "line-1",            K_PREV_LINE,        0,
  514. X    "line=@",            K_GOTO_LINE,        K_ONLY_MORE,
  515. X
  516. X    "macro",            K_MACRO,        0,
  517. X    "mail",            K_MAIL_OR_FORWARD,    0,
  518. X    "message",            K_LAST_MESSAGE,        0,
  519. X
  520. X    "next-article",        K_NEXT_ARTICLE,        K_ONLY_MORE,
  521. X    "next-group",        K_NEXT_GROUP_NO_UPDATE,    0,
  522. X    "next-subject",        K_NEXT_SUBJECT,        K_ONLY_MORE,
  523. X    "nil",            K_UNBOUND,        0,
  524. X
  525. X    "overview",            K_GROUP_OVERVIEW,    0,
  526. X
  527. X    "page+1",            K_NEXT_PAGE,        0,
  528. X    "page+1/2",            K_NEXT_HALF_PAGE,    K_ONLY_MORE,
  529. X    "page-1",            K_PREV_PAGE,        0,
  530. X    "page-1/2",            K_PREV_HALF_PAGE,    K_ONLY_MORE,
  531. X    "page=$",            K_LAST_PAGE,        0,
  532. X    "page=0",            K_HEADER_PAGE,        0,
  533. X    "page=1",            K_FIRST_PAGE,        0,
  534. X    "page=@",            K_GOTO_PAGE,        K_ONLY_MORE,
  535. X
  536. X    "patch",            K_PATCH,        0,
  537. X    "post",            K_POST,            0,
  538. X    "preview",            K_PREVIEW,        0,
  539. X    "previous",            K_PREVIOUS,        0,
  540. X    "print",            K_PRINT,        0,
  541. X
  542. X    "quit",            K_QUIT,            0,
  543. X
  544. X    "read-return",        K_READ_GROUP_THEN_SAME,    K_ONLY_MENU,
  545. X    "read-skip",        K_READ_GROUP_UPDATE,    0,
  546. X    "redraw",            K_REDRAW,        0,
  547. X    "reply",            K_REPLY,        0,
  548. X    "rot13",            K_ROT13,        K_ONLY_MORE,
  549. X
  550. X    "save-body",        K_SAVE_NO_HEADER,    0,
  551. X    "save-full",        K_SAVE_FULL_HEADER,    0,
  552. X    "save-short",        K_SAVE_SHORT_HEADER,    0,
  553. X    "select",            K_SELECT,        K_ONLY_MENU,
  554. X    "select-auto",        K_AUTO_SELECT,        K_ONLY_MENU,
  555. X    "select-invert",        K_SELECT_INVERT,    K_ONLY_MENU,
  556. X    "select-range",        K_SELECT_RANGE,        K_ONLY_MENU,
  557. X    "select-subject",        K_SELECT_SUBJECT,    0,
  558. X    "shell",            K_SHELL,        0,
  559. X    "skip-lines",        K_SKIP_LINES,        0,
  560. X
  561. X    "unselect-all",        K_UNSELECT_ALL,        K_ONLY_MENU,
  562. X    "unshar",            K_UNSHAR,        0,
  563. X    "unsub",            K_UNSUBSCRIBE,        0,
  564. X
  565. X    "version",            K_VERSION,        0,
  566. X
  567. X    (char *)NULL,        0,            0
  568. X};
  569. X
  570. Xstatic int name_map_size;
  571. Xstatic int max_cmd_name_length = 14;    /* recalculate if table is changed */
  572. X
  573. Xexport key_type global_key_map[KEY_MAP_SIZE];
  574. X
  575. X
  576. Xinit_key_map()
  577. X{
  578. X    register int c;
  579. X    register struct command_name_map *cnmp;
  580. X
  581. X    for (c = 0; c < KEY_MAP_SIZE; c++) global_key_map[c] = c;
  582. X
  583. X    for (cnmp = command_name_map; cnmp->cmd_name; cnmp++);
  584. X    name_map_size = cnmp - command_name_map;
  585. X}
  586. X
  587. X
  588. Xlookup_command(command, restriction)
  589. Xchar *command;
  590. Xint restriction;
  591. X{
  592. X    register struct command_name_map *cnmp;
  593. X    register i, j, k, t;
  594. X
  595. X    i = 0; j = name_map_size - 1;
  596. X
  597. X    while (i <= j) {
  598. X    k = (i + j) / 2;
  599. X    cnmp = &command_name_map[k];
  600. X
  601. X    if ( (t=strcmp(command, cnmp->cmd_name)) > 0)
  602. X        i = k+1;
  603. X    else
  604. X    if (t < 0)
  605. X        j = k-1;
  606. X    else {
  607. X        if (cnmp->cmd_restriction == 0
  608. X        || (cnmp->cmd_restriction & restriction))
  609. X        return cnmp->cmd_code;
  610. X        break;
  611. X    }
  612. X    }
  613. X
  614. X    return K_INVALID;
  615. X}
  616. X
  617. X
  618. Xcmd_completion(path, index)
  619. Xchar *path;
  620. Xint index;
  621. X{
  622. X    static char *head, *tail = NULL;
  623. X    static int len;
  624. X    static struct command_name_map *cmd, *help_cmd;
  625. X
  626. X    if (index < 0) return 0;
  627. X
  628. X    if (path) {
  629. X    head = path;
  630. X    tail = path + index;
  631. X    while (*head && isspace(*head)) head++;
  632. X    help_cmd = cmd = command_name_map;
  633. X    len = tail - head;
  634. X
  635. X    return 1;
  636. X    }
  637. X
  638. X    if (index) {
  639. X    list_completion((char *)NULL);
  640. X
  641. X    if (help_cmd->cmd_name == NULL)
  642. X        help_cmd = command_name_map;
  643. X
  644. X    for (;help_cmd->cmd_name; help_cmd++) {
  645. X        index = strncmp(help_cmd->cmd_name, head, len);
  646. X        if (index < 0) continue;
  647. X        if (index > 0) {
  648. X        help_cmd = command_name_map;
  649. X        break;
  650. X        }
  651. X        if (list_completion(help_cmd->cmd_name) == 0) break;
  652. X    }
  653. X    fl;
  654. X    return 1;
  655. X    }
  656. X
  657. X    for (; cmd->cmd_name; cmd++) {
  658. X    if (len == 0)
  659. X        index = 0;
  660. X    else
  661. X        index = strncmp(cmd->cmd_name, head, len);
  662. X    if (index < 0) continue;
  663. X    if (index > 0) break;
  664. X    if (cmd->cmd_code == K_MACRO ||
  665. X        cmd->cmd_code == K_ARTICLE_ID ||
  666. X        cmd->cmd_code == K_EQUAL_KEY)
  667. X        sprintf(tail, "%s ", cmd->cmd_name + len);
  668. X    else
  669. X        strcpy(tail, cmd->cmd_name + len);
  670. X    cmd++;
  671. X    return 1;
  672. X    }
  673. X    return 0;
  674. X}
  675. X
  676. X
  677. Xchar *command_name(cmd)
  678. Xint cmd;
  679. X{
  680. X    register struct command_name_map *cnmp;
  681. X
  682. X    cmd &= ~GETC_COMMAND;
  683. X
  684. X    for (cnmp = command_name_map; cnmp->cmd_name; cnmp++)
  685. X    if (cnmp->cmd_code == cmd) return cnmp->cmd_name;
  686. X
  687. X    return "unknown";
  688. X}
  689. X
  690. X
  691. X/*
  692. X * convert key name into ascii code
  693. X *
  694. X *    key names are:
  695. X *        c    character c
  696. X *        ^C    control-C
  697. X *        0xNN    hex value (0..0x7f)
  698. X *        0NNN    octal value (0..0177)
  699. X *        NNN    decimal value (0..127)
  700. X *        up, down, left, rigth    arrow keys
  701. X *        #0..#9            function keys (initially undefined)
  702. X */
  703. X
  704. Xkey_type parse_key(str)
  705. Xchar *str;
  706. X{
  707. X    int x;
  708. X
  709. X    if (str[1] == NUL)
  710. X    return str[0] & 0177;
  711. X
  712. X    if (str[0] == '^')
  713. X    if (str[1] == '?')
  714. X        return 0177;
  715. X    else
  716. X        return CONTROL_(str[1]);
  717. X
  718. X    if (isdigit(str[0])) {
  719. X    if (str[0] == '0')
  720. X        if (str[1] == 'x')
  721. X        sscanf(str+2, "%x", &x);
  722. X        else
  723. X        sscanf(str+1, "%o", &x);
  724. X    else
  725. X        sscanf(str, "%d", &x);
  726. X
  727. X    return x & 0177;
  728. X    }
  729. X
  730. X    if (str[0] == '#' && isdigit(str[1]))
  731. X    return K_function(str[1] - '0');
  732. X
  733. X    if (strcmp(str, "up") == 0)
  734. X    return K_up_arrow;
  735. X
  736. X    if (strcmp(str, "down") == 0)
  737. X    return K_down_arrow;
  738. X
  739. X    if (strcmp(str, "left") == 0)
  740. X    return K_left_arrow;
  741. X
  742. X    if (strcmp(str, "right") == 0)
  743. X    return K_right_arrow;
  744. X
  745. X    init_message("unknown key: %s", str);
  746. X
  747. X    return 0200;
  748. X}
  749. X
  750. Xchar *key_name(c)
  751. Xkey_type c;
  752. X{
  753. X    static char buf[3];
  754. X
  755. X    if (c & 0200) {
  756. X    switch (c) {
  757. X     case K_up_arrow:
  758. X        return "up";
  759. X     case K_down_arrow:
  760. X        return "down";
  761. X     case K_left_arrow:
  762. X        return "left";
  763. X     case K_right_arrow:
  764. X        return "right";
  765. X     default:
  766. X        buf[0] = '#';
  767. X        buf[1] = (c - K_function(0)) + '0';
  768. X        buf[2] = NUL;
  769. X        goto out;
  770. X    }
  771. X    }
  772. X
  773. X    if (c < SP) {
  774. X    buf[0] = '^';
  775. X    buf[1] = c + '@';
  776. X    buf[2] = NUL;
  777. X    goto out;
  778. X    }
  779. X
  780. X    if (c == 0177) {
  781. X    strcpy(buf, "^?");
  782. X    goto out;
  783. X    }
  784. X
  785. X    buf[0] = c;
  786. X    buf[1] = NUL;
  787. X
  788. X out:
  789. X    return buf;
  790. X}
  791. X
  792. X
  793. Xdump_global_map()
  794. X{
  795. X    register key_type c;
  796. X
  797. X    clrdisp();
  798. X    so_printf("\1REMAPPED KEYS\1\n\n");
  799. X    pg_init(2, 4);
  800. X
  801. X    for (c = 0; c < KEY_MAP_SIZE; c++)
  802. X    if (c != global_key_map[c]) {
  803. X        if (pg_next() < 0) break;
  804. X        printf("%s", key_name(c));
  805. X        pg_indent(6);
  806. X        printf("-> %s", key_name(global_key_map[c]));
  807. X    }
  808. X
  809. X    pg_end();
  810. X}
  811. X
  812. X
  813. Xdump_key_map(map, where, restriction)
  814. Xint map[];
  815. Xchar *where;
  816. Xint restriction;
  817. X{
  818. X    register struct command_name_map *cnmp;
  819. X    register key_type c;
  820. X    register int code, first_prt;
  821. X    
  822. X    clrdisp();
  823. X    so_printf("\1KEY BINDINGS (%s)\1\n\n", where);
  824. X
  825. X    if (restriction == K_ONLY_MENU) {
  826. X    printf("\rarticle:  ");
  827. X    for (c = 0; c < KEY_MAP_SIZE; c++)
  828. X        if (map[c] & K_ARTICLE_ID) printf("%s", key_name(c));
  829. X    }
  830. X
  831. X    pg_init(4, 2);
  832. X
  833. X    for (cnmp = command_name_map; cnmp->cmd_name; cnmp++) {
  834. X    if (cnmp->cmd_restriction && cnmp->cmd_restriction != restriction)
  835. X        continue;
  836. X    if (cnmp->cmd_code == K_UNBOUND) continue;
  837. X    if (cnmp->cmd_code == K_MACRO) continue;
  838. X
  839. X    code = cnmp->cmd_code;
  840. X    first_prt = 1;
  841. X
  842. X    for (c = 0; c < KEY_MAP_SIZE; c++)
  843. X        if (map[c] == code) {
  844. X        if (first_prt) {
  845. X            if (pg_next() < 0) goto out;
  846. X            fputs(cnmp->cmd_name, stdout);
  847. X            pg_indent(max_cmd_name_length);
  848. X            first_prt = 0;
  849. X        }
  850. X        printf(" %s", key_name(c));
  851. X        }
  852. X    }
  853. X
  854. X    for (c = 0; c < KEY_MAP_SIZE; c++)
  855. X    if (map[c] & K_MACRO) {
  856. X        if (pg_next() < 0) goto out;
  857. X        printf("macro %d: %s", (map[c] & ~K_MACRO), key_name(c));
  858. X    }
  859. X
  860. X out:
  861. X    pg_end();
  862. X}
  863. END_OF_FILE
  864.   if test 17311 -ne `wc -c <'keymap.c'`; then
  865.     echo shar: \"'keymap.c'\" unpacked with wrong size!
  866.   fi
  867.   # end of 'keymap.c'
  868. fi
  869. if test -f 'menu.c' -a "${1}" != "-c" ; then 
  870.   echo shar: Will not clobber existing file \"'menu.c'\"
  871. else
  872.   echo shar: Extracting \"'menu.c'\" \(33007 characters\)
  873.   sed "s/^X//" >'menu.c' <<'END_OF_FILE'
  874. X/*
  875. X *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  876. X *
  877. X *     selection mode menu
  878. X */
  879. X
  880. X#include "config.h"
  881. X#include "articles.h"
  882. X#include "term.h"
  883. X#include "keymap.h"
  884. X#include "menu.h"
  885. X#include "regexp.h"
  886. X
  887. Ximport char *news_lib_directory;
  888. X
  889. Xexport int  preview_window = 0;    /* size of preview window */
  890. Xexport int  fmt_linenum    = 1; /* menu line format */
  891. Xexport int  fmt_rptsubj    = 0; /* repeat identical subjects if !0 */
  892. Xexport int  novice       = 1; /* novice mode -- use extended prompts */
  893. Xexport int  long_menu       = 0; /* don't put empty lines around menu lines */
  894. Xexport int  delay_redraw   = 0; /* prompt again if :-command clears screen */
  895. Xexport int  slow_mode       = 0;    /* mark selected articles with *s */
  896. Xexport int  re_layout      = 0; /* Re: format presentation on menus */
  897. Xexport int  collapse_subject = 25; /* collapse long subjects at position */
  898. Xexport int  conf_group_entry = 0; /* ask whether group should be entered */
  899. Xexport int  conf_entry_limit = 0; /* ask only if more than .. unread */
  900. X
  901. Xexport int  auto_preview_mode = 0; /* preview rather than select */
  902. Xexport int  preview_continuation = 12; /* what to do after preview */
  903. Xexport int  preview_mark_read = 1; /* previewed articles are A_READ */
  904. Xexport int  select_on_sender = 0; /* + command selects on sender */
  905. X
  906. Xexport char delayed_msg[100] = "";    /* give to msg() after redraw */
  907. X
  908. Xexport int  flush_typeahead = 0;
  909. X
  910. Ximport int also_read_articles;
  911. Ximport int merged_menu;
  912. Ximport int case_fold_search;
  913. X
  914. Xextern group_completion();
  915. X
  916. Xstatic regexp *regular_expr = NULL;
  917. X
  918. Xstatic int firstl;    /* first menu line */
  919. X
  920. Xstatic article_number firsta;    /* first article on menu (0 based) */
  921. Xstatic article_number nexta;    /* first article on next menu */
  922. Xstatic int cura;    /* current article */
  923. Xstatic int next_cura;    /* article to become cura if >= 0 */
  924. Xstatic int numa;    /* no of articles on menu - 1 */
  925. Xstatic attr_type last_attr;
  926. X
  927. X#define INTERVAL1    ('z' - 'a' + 1)
  928. X#define INTERVAL2    ('9' - '0' + 1)
  929. X
  930. Xchar ident[] = "abcdefghijklmnopqrstuvwxyz0123456789";
  931. X
  932. Xchar attributes[30] = " .,+=#! **"; /* Corresponds to A_XXXX in data.h */
  933. X
  934. Xstatic prt_replies(level)
  935. X{
  936. X    int re;
  937. X
  938. X    if (level == 0) return 0;
  939. X    re = level & 0x80;
  940. X    level &= 0x7f;
  941. X
  942. X    switch (re_layout) {
  943. X     case 1:
  944. X    if (!re) return 0;
  945. X    so_printf(">");
  946. X    return 1;
  947. X     case 2:
  948. X    so_printf("%d>", level);
  949. X    return level < 10 ? 2 : 3;
  950. X     case 3:
  951. X    so_printf("Re: ");
  952. X    return 4;
  953. X    }
  954. X
  955. X    if (level < 10) {
  956. X    so_printf("%-.*s", level, ">>>>>>>>>");
  957. X    return level;
  958. X    }
  959. X
  960. X    so_printf(">>>%3d >>>>", level);
  961. X    return 11;
  962. X}
  963. X
  964. Xstatic mark()
  965. X{
  966. X    register article_header *ah;
  967. X    int lno, lnum, lsubj, lname;
  968. X
  969. X    ah = articles[firsta + cura];
  970. X    last_attr = ah->attr;
  971. X
  972. X    if (last_attr == ah->disp_attr) return;
  973. X    if (cura < 0 || cura > numa) return;
  974. X
  975. X    lno = firstl + cura;
  976. X    if (ah->disp_attr == A_NOT_DISPLAYED) {
  977. X    gotoxy(0, lno);
  978. X    putchar(ident[cura]);
  979. X    goto print_line;
  980. X    }
  981. X
  982. X    /* A_AUTO_SELECT will not occur here! */
  983. X
  984. X    if (!slow_mode)
  985. X    if (last_attr == A_SELECT) {
  986. X        if ((ah->disp_attr & A_SELECT) == 0) goto print_line;
  987. X    } else {
  988. X        if (ah->disp_attr & A_SELECT) goto print_line;
  989. X    }
  990. X
  991. X    gotoxy(1, lno);
  992. X    putchar(attributes[ah->attr]);
  993. X    goto out;
  994. X
  995. X print_line:
  996. X    /* menu line formats:
  997. X                1  3    8 10     20 22        xx
  998. X        :  :    :  :      :  :        :
  999. X       -1    id name:8 subject
  1000. X       0    id name           subject     +lines
  1001. X       1    id name       lines  subject
  1002. X       2    id  lines  subject
  1003. X       3    id subject
  1004. X       4    id   subject  (or as 1 if short subject)
  1005. X     */
  1006. X
  1007. X    if (fmt_linenum > 4) fmt_linenum = 1;
  1008. X
  1009. X    if (!slow_mode && (ah->attr & A_SELECT)) {
  1010. X    if (so_gotoxy(1, lno, 1) == 0)
  1011. X        putchar(attributes[A_SELECT]);
  1012. X    } else {
  1013. X        gotoxy(1, lno);
  1014. X    putchar(attributes[ah->attr]);
  1015. X    }
  1016. X
  1017. X    if (ah->lines <    10) lnum = 1; else
  1018. X    if (ah->lines <   100) lnum = 2; else
  1019. X    if (ah->lines <  1000) lnum = 3; else
  1020. X    if (ah->lines < 10000) lnum = 4; else lnum = 5;
  1021. X
  1022. X    lsubj = Columns - cookie_size - 2; /* ident char + space */
  1023. X
  1024. X    switch (fmt_linenum) {
  1025. X
  1026. X     case -1:
  1027. X    lsubj -= 9;
  1028. X    so_printf("%-8.8s ", ah->sender);
  1029. X    break;
  1030. X
  1031. X     case 0:
  1032. X    lsubj -= NAME_LENGTH + 1 + 2 + lnum;  /* name. .subj. +.lines */
  1033. X    so_printf("%-*s ", NAME_LENGTH, ah->sender);
  1034. X    break;
  1035. X
  1036. X     case 4:
  1037. X    if (ah->subj_length > (lsubj - NAME_LENGTH - 5))
  1038. X        if (fmt_rptsubj || lno == firstl || (ah->flag & A_SAME) == 0) {
  1039. X        so_printf("  ");
  1040. X        lsubj -= 2;
  1041. X        break;
  1042. X        }
  1043. X    /* else use layout 1, so fall thru */
  1044. X
  1045. X     case 1:
  1046. X    lsubj -= NAME_LENGTH + 5;
  1047. X    /* name.lines.  .subj (name may be shortened) */
  1048. X    lname = NAME_LENGTH + 2 - lnum;
  1049. X    so_printf("%-*.*s ", lname, lname, ah->sender);
  1050. X    so_printf(ah->lines >= 0 ? "%d  " : "?  ", ah->lines);
  1051. X    break;
  1052. X
  1053. X     case 2:
  1054. X    lsubj -= 6;
  1055. X    so_printf("%5d ", ah->lines);
  1056. X    break;
  1057. X
  1058. X     case 3:
  1059. X    break;
  1060. X    }
  1061. X
  1062. X    if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) {
  1063. X    if (ah->replies == 0 || prt_replies(ah->replies) == 0)
  1064. X        so_printf("-");
  1065. X    } else {
  1066. X    lsubj -= prt_replies(ah->replies);
  1067. X    if (lsubj >= ah->subj_length)
  1068. X        so_printf("%s", ah->subject);
  1069. X    else
  1070. X    if (collapse_subject < 0)
  1071. X        so_printf("%-.*s", lsubj, ah->subject);
  1072. X    else {
  1073. X        if (collapse_subject > 0)
  1074. X        so_printf("%-.*s", collapse_subject, ah->subject);
  1075. X        lsubj -= 2 + collapse_subject;
  1076. X        so_printf("<>%s", ah->subject + ah->subj_length - lsubj);
  1077. X    }
  1078. X    }
  1079. X
  1080. X    if (fmt_linenum == 0)
  1081. X    so_printf(ah->lines >= 0 ? " +%d" : " +?", ah->lines);
  1082. X
  1083. X    so_end();
  1084. X
  1085. X out:
  1086. X    ah->disp_attr = last_attr;
  1087. X    return;
  1088. X}
  1089. X
  1090. Xstatic new_mark(how)
  1091. Xattr_type how;
  1092. X{
  1093. X    articles[firsta + cura]->attr = how;
  1094. X    mark();
  1095. X}
  1096. X
  1097. Xstatic toggle()
  1098. X{
  1099. X    last_attr = articles[firsta + cura]->attr =
  1100. X    articles[firsta + cura]->attr & A_SELECT ? 0 : A_SELECT;
  1101. X}
  1102. X
  1103. Xstatic do_auto_kill()
  1104. X{
  1105. X    register article_number i;
  1106. X    register article_header *ah, **ahp;
  1107. X    int any = 0;
  1108. X
  1109. X    for (i = 0, ahp = articles; i < n_articles; i++, ahp++) {
  1110. X    ah = *ahp;
  1111. X    if (auto_select_article(ah, 0)) {
  1112. X        ah->attr = A_KILL;
  1113. X        any = 1;
  1114. X    }
  1115. X    }
  1116. X    return any;
  1117. X}
  1118. X
  1119. X/*
  1120. X *    perform auto selections that are not already selected
  1121. X *    if article is in range firsta..firsta+numa (incl) mark article
  1122. X */
  1123. X
  1124. Xstatic do_auto_select(re, mode)
  1125. Xregexp *re;
  1126. Xint mode;
  1127. X{
  1128. X    register article_number i;
  1129. X    register article_header *ah, **ahp;
  1130. X    int count = 0, o_cura;
  1131. X
  1132. X    o_cura = cura;
  1133. X
  1134. X    for (i = 0, ahp = articles; i < n_articles; i++, ahp++) {
  1135. X    ah = *ahp;
  1136. X    if (re != NULL) {
  1137. X        if (!regexec_cf(re, select_on_sender ? ah->sender : ah->subject)) continue;
  1138. X    } else
  1139. X        if (!auto_select_article(ah, mode)) continue;
  1140. X
  1141. X    count++;
  1142. X    if (ah->attr & A_SELECT) continue;
  1143. X    if (firsta <= i && i <= (firsta+numa)) {
  1144. X        cura = i - firsta;
  1145. X        new_mark(A_SELECT);
  1146. X    } else
  1147. X        ah->attr = A_SELECT;
  1148. X    }
  1149. X
  1150. X    if (count)
  1151. X    msg("Selected %d article%s", count, plural((long)count));
  1152. X    else
  1153. X    msg("No selections");
  1154. X    
  1155. X    cura = o_cura;
  1156. X}
  1157. X
  1158. Xstatic quit_preview(cmd)
  1159. Xint cmd;
  1160. X{
  1161. X    int op;
  1162. X
  1163. X    if ((firsta + cura) >= n_articles) return 1;
  1164. X    op = preview_continuation;
  1165. X    if (cmd == MC_PREVIEW_NEXT)    op /= 10;
  1166. X    op %= 10;
  1167. X    switch (op) {
  1168. X     case 0:
  1169. X    return 1;
  1170. X     case 1:
  1171. X    return 0;
  1172. X     case 2:
  1173. X    return (articles[firsta+cura]->flag & (A_SAME | A_ALMOST_SAME)) == 0;
  1174. X    }
  1175. X    return 0;
  1176. X}
  1177. X
  1178. X
  1179. Xstatic show_articles()
  1180. X{
  1181. X    register article_number cur, next, temp;
  1182. X    register article_header *ah;
  1183. X    article_number elim_list[1];
  1184. X    register int mode;
  1185. X    int cmd, prev = -1, again;
  1186. X    attr_type o_attr;
  1187. X
  1188. X    do {
  1189. X    for (cur = 0; cur < n_articles; cur++) {
  1190. X        if (articles[cur]->attr & A_SELECT) break;
  1191. X    }
  1192. X
  1193. X    while (cur < n_articles) {
  1194. X
  1195. X        for (next = cur+1; next < n_articles; next++) {
  1196. X        if (articles[next]->attr & A_SELECT) break;
  1197. X        }
  1198. X
  1199. X     show:
  1200. X        ah = articles[cur];
  1201. X        o_attr = ah->attr;
  1202. X        ah->attr = 0;
  1203. X
  1204. X        mode = 0;
  1205. X        if (prev >= 0) mode |= MM_PREVIOUS;
  1206. X        if (next == n_articles) mode |= MM_LAST_SELECTED;
  1207. X        if ((cur + 1) >= n_articles) mode |= MM_LAST_ARTICLE;
  1208. X        if (cur == 0) mode |= MM_FIRST_ARTICLE;
  1209. X
  1210. X        cmd = more(ah, mode, 0);
  1211. X
  1212. X        switch (cmd) {
  1213. X
  1214. X         case MC_DO_KILL:
  1215. X        if (do_auto_kill()) {
  1216. X            elim_list[0] = next;
  1217. X            elim_articles(elim_list, 1);
  1218. X            cur = elim_list[0];
  1219. X            /* if next was n_articles, cur will be 0 */
  1220. X            if (cur >= n_articles || cur < 0
  1221. X            || (articles[cur]->attr & A_SELECT) == 0)
  1222. X            cur = n_articles;
  1223. X            continue;
  1224. X        }
  1225. X        break;
  1226. X
  1227. X         case MC_DO_SELECT:
  1228. X        for (temp = cur+1; temp < n_articles; temp++) {
  1229. X            if (auto_select_article(ah = articles[temp], 2)) {
  1230. X            ah->attr = A_SELECT;
  1231. X            if (temp < next) next = temp;
  1232. X            }
  1233. X        }
  1234. X        break;
  1235. X
  1236. X         case MC_PREV:
  1237. X        if (prev == next) break;
  1238. X
  1239. X        ah->attr = o_attr;
  1240. X        next = cur; cur = prev; prev = next;
  1241. X        goto show;
  1242. X
  1243. X         case MC_NEXTSUBJ:
  1244. X        ah->attr = A_READ;
  1245. X        for (next = cur+1; next < n_articles; next++) {
  1246. X            if (((ah = articles[next])->flag & (A_SAME | A_ALMOST_SAME)) == 0) break;
  1247. X            ah->attr = A_READ;
  1248. X        }
  1249. X        for (; next < n_articles; next++) {
  1250. X            if (articles[next]->attr & A_SELECT) break;
  1251. X        }
  1252. X        break;
  1253. X
  1254. X         case MC_ALLSUBJ:
  1255. X        for (next = cur+1; next < n_articles; next++) {
  1256. X            ah = articles[next];
  1257. X            if ((ah->flag & (A_SAME | A_ALMOST_SAME)) == 0) break;
  1258. X            ah->attr = A_SELECT;
  1259. X        }
  1260. X        for (next = cur+1; next < n_articles; next++)
  1261. X            if (articles[next]->attr & A_SELECT) break;
  1262. X        break;
  1263. X
  1264. X         case MC_MENU:
  1265. X        ah->attr = o_attr;
  1266. X        if (nexta - firsta < n_articles)
  1267. X            if ((firsta = cur - 5) < 0) firsta = 0;
  1268. X        next_cura = cur - firsta;
  1269. X
  1270. X        return MC_MENU;
  1271. X
  1272. X         case MC_NEXT:
  1273. X        if (ah->attr == 0)    /* Not set by more (sufficient ???) */
  1274. X            ah->attr = A_READ;
  1275. X        break;
  1276. X
  1277. X         case MC_BACK_ART:
  1278. X        ah->attr = o_attr ? o_attr : A_SEEN;
  1279. X        next = cur - 1;
  1280. X        break;
  1281. X
  1282. X         case MC_FORW_ART:
  1283. X        ah->attr = o_attr ? o_attr : A_SEEN;
  1284. X        next = cur + 1;
  1285. X        break;
  1286. X
  1287. X         case MC_NEXTGROUP:
  1288. X         case MC_REENTER_GROUP:
  1289. X         case MC_QUIT:
  1290. X        ah->attr = o_attr;
  1291. X        return cmd;
  1292. X
  1293. X         case MC_READGROUP:
  1294. X        return cmd;
  1295. X        }
  1296. X
  1297. X        prev = cur; cur = next;
  1298. X    }
  1299. X
  1300. X    for (cur = 0; cur < n_articles; cur++)
  1301. X        if (articles[cur]->attr & A_SELECT) break;
  1302. X    if (cur < n_articles) continue;
  1303. X
  1304. X    again = 0;
  1305. X    for (cur = 0; cur < n_articles; cur++) {
  1306. X        ah = articles[cur];
  1307. X        if (ah->attr == A_LEAVE) {
  1308. X        if (again == 0) {
  1309. X            prompt("Show left over articles again now? ");
  1310. X            if (yes(0) <= 0) break;
  1311. X        }
  1312. X        ah->attr = A_SELECT;
  1313. X        again++;
  1314. X        }
  1315. X    }
  1316. X
  1317. X    if (again > 1)
  1318. X        sprintf(delayed_msg, "Showing %ld articles again", again);
  1319. X    } while (again);
  1320. X
  1321. X    return MC_READGROUP;
  1322. X}
  1323. X
  1324. Xstatic int article_id;
  1325. Xstatic int cur_key;
  1326. X
  1327. Xstatic int get_k_cmd()
  1328. X{
  1329. X    extern int any_message;
  1330. X    register int c, map;
  1331. X
  1332. X    if (flush_typeahead) flush_input();
  1333. X
  1334. X loop:
  1335. X
  1336. X    article_id = -1;
  1337. X
  1338. X    if ((c = get_c()) & GETC_COMMAND) {
  1339. X    cur_key = K_interrupt;
  1340. X    map = c & ~GETC_COMMAND;
  1341. X    } else {
  1342. X    cur_key = c;
  1343. X    map = menu_key_map[c];
  1344. X    }
  1345. X    if (s_hangup) map = K_QUIT;
  1346. X
  1347. X    if (map & K_MACRO) {
  1348. X    m_invoke(map & ~K_MACRO);
  1349. X    goto loop;
  1350. X    }
  1351. X
  1352. X    if (map & K_ARTICLE_ID) {
  1353. X    article_id = map & ~K_ARTICLE_ID;
  1354. X    map = K_ARTICLE_ID;
  1355. X
  1356. X    if (article_id < 0 || article_id > numa) {
  1357. X        ding();
  1358. X        goto loop;
  1359. X    }
  1360. X    }
  1361. X
  1362. X    if (any_message) clrmsg(-1);
  1363. X    return map;
  1364. X}
  1365. X
  1366. X
  1367. Xchar *pct(start, end, first, last)
  1368. Xlong start, end, first, last;
  1369. X{
  1370. X    long n = end - start;
  1371. X    static char buf[16];
  1372. X    char *fmt;
  1373. X
  1374. X    if (first <= start || n <= 0)
  1375. X    if (last >= end || n <= 0)
  1376. X        return "All";
  1377. X    else
  1378. X        fmt = "Top %d%%";
  1379. X    else
  1380. X    if (last >= end)
  1381. X        return "Bot";
  1382. X    else
  1383. X        fmt = "%d%%";
  1384. X
  1385. X    sprintf(buf, fmt, ((last - start) * 100)/n);
  1386. X    return buf;
  1387. X}
  1388. X
  1389. Xstatic repl_attr(first, last, old, new, update)
  1390. Xregister article_number first, last;
  1391. Xregister attr_type old, new;
  1392. Xint update;
  1393. X{
  1394. X    int any;
  1395. X
  1396. X    if (new == old) return 0;
  1397. X    if (new == A_KILL) update = 0;
  1398. X
  1399. X    any = 0;
  1400. X    while (first < last) {
  1401. X    if (old == A_KILL || articles[first]->attr == old) {
  1402. X        articles[first]->attr = new;
  1403. X        if (update) {
  1404. X        cura = first-firsta;
  1405. X        mark();
  1406. X        }
  1407. X        any = 1;
  1408. X    }
  1409. X
  1410. X    first++;
  1411. X    }
  1412. X    return any;
  1413. X}
  1414. X
  1415. X
  1416. Xstatic repl_attr_all(old, new, update)
  1417. Xattr_type old, new;
  1418. Xint update;
  1419. X{
  1420. X    return repl_attr((article_number)0, n_articles, old, new, update);
  1421. X}
  1422. X
  1423. Xstatic get_purpose(purpose)
  1424. Xchar *purpose;
  1425. X{
  1426. X#ifdef NNTP
  1427. X    return;            /* newsgroups file is not available */
  1428. X#else
  1429. X    FILE *f;
  1430. X    char line[256], group[80];
  1431. X    register char *cp, *pp;
  1432. X    register int len;
  1433. X
  1434. X    f = open_file(relative(news_lib_directory, "newsgroups"), OPEN_READ);
  1435. X    if (f == NULL) return;
  1436. X
  1437. X    sprintf(group, "%s\t", current_group->group_name);
  1438. X    len = current_group->group_name_length + 1;
  1439. X
  1440. X    while (fgets(line, 256, f) != NULL) {
  1441. X    if (strncmp(line, group, len)) continue;
  1442. X    cp = line + len;
  1443. X    while (*cp && isspace(*cp)) cp++;
  1444. X    for (pp = purpose, len = 76; --len >= 0 && *cp && *cp != NL; )
  1445. X        *pp++ = *cp++;
  1446. X    *pp = NUL;
  1447. X    }
  1448. X
  1449. X    fclose(f);
  1450. X#endif
  1451. X}
  1452. X
  1453. X
  1454. Xmenu(print_header)
  1455. Xfct_type print_header;
  1456. X{
  1457. X    register         k_cmd, cur_k_cmd;
  1458. X    register        article_header *ah;
  1459. X    int            last_k_cmd;
  1460. X    int         menu_cmd, temp;
  1461. X    int         save_selected;
  1462. X    article_number    last_save;
  1463. X    attr_type        orig_attr, junk_attr;
  1464. X    int            doing_unshar, did_unshar, junk_prompt;
  1465. X    char         *fname, *savemode, *init_save();
  1466. X    int         maxa;    /* max no of articles per menu page */
  1467. X    int         o_firsta, o_mode;    /* for recursive calls */
  1468. X    static        menu_level = 0;
  1469. X    char        purpose[80], pr_fmt[60];
  1470. X    extern int         enable_stop, file_completion();
  1471. X    extern int        alt_cmd_key, in_menu_mode;
  1472. X    article_number    elim_list[3];
  1473. X    int            entry_check;
  1474. X
  1475. X#define    menu_return(cmd) \
  1476. X    { menu_cmd = (cmd); goto menu_exit; }
  1477. X
  1478. X    flush_input();
  1479. X
  1480. X    o_firsta = firsta;
  1481. X    o_mode = in_menu_mode;
  1482. X    in_menu_mode = 1;
  1483. X
  1484. X    menu_level++;
  1485. X
  1486. X    entry_check = menu_level == 1 && conf_group_entry &&
  1487. X    current_group->unread_count > conf_entry_limit;
  1488. X
  1489. X    sprintf(pr_fmt,
  1490. X        menu_level == 1 ?
  1491. X          "\1\2-- SELECT %s-----%%s-----\1" :
  1492. X          "\1\2-- SELECT %s-----%%s-----<%s%d>--\1",
  1493. X          novice ? "-- help:? " : "",
  1494. X          novice ? "level " : "",
  1495. X          menu_level);
  1496. X
  1497. X    purpose[0] = NUL;
  1498. X    if (!merged_menu && current_group->group_flag & G_NEW)
  1499. X    get_purpose(purpose);
  1500. X
  1501. X    firsta = 0;
  1502. X    while (firsta < n_articles && articles[firsta]->attr == A_SEEN)
  1503. X    firsta++;
  1504. X
  1505. X    if (firsta == n_articles) firsta = 0;
  1506. X
  1507. X    next_cura = -1;
  1508. X    cur_k_cmd = K_UNBOUND;
  1509. X
  1510. X#ifdef HAVE_JOBCONTROL
  1511. X#define    REDRAW_CHECK    if (s_redraw) goto do_redraw
  1512. X
  1513. X do_redraw:
  1514. X    /* safe to clear here, because we are going to redraw anyway */
  1515. X    s_redraw = 0;
  1516. X#else
  1517. X#define REDRAW_CHECK
  1518. X#endif
  1519. X
  1520. X redraw:
  1521. X    s_keyboard = 0;
  1522. X
  1523. X empty_menu_hack:    /* do: "s_keyboard=1; goto empty_menu_hack;" */
  1524. X    if (!slow_mode) s_keyboard = 0;
  1525. X
  1526. X    nexta = firsta;
  1527. X
  1528. X    clrdisp();
  1529. X
  1530. X    firstl = CALL(print_header)();
  1531. X
  1532. X    if (entry_check && menu_level == 1) {
  1533. X    /* we do it here to avoid redrawing the group header */
  1534. X    entry_check = 0;
  1535. X    prompt_line = firstl;
  1536. X    prompt("\1Enter?\1 ");
  1537. X    if ((temp = yes(0)) <= 0) {
  1538. X        if (temp < 0) {
  1539. X        prompt("\1Mark as read?\1 ");
  1540. X        if ((temp = yes(0)) < 0) menu_return(ME_QUIT);
  1541. X        if (temp > 0) repl_attr_all(A_KILL, A_READ, 0);
  1542. X        }
  1543. X        menu_return(ME_NEXT);
  1544. X    }
  1545. X
  1546. X    gotoxy(0, firstl);
  1547. X    clrline();
  1548. X    }
  1549. X
  1550. X    maxa = Lines - preview_window - firstl - 2;
  1551. X    if (!long_menu) firstl++, maxa -= 2;
  1552. X
  1553. X    if (maxa > (INTERVAL1 + INTERVAL2))
  1554. X    maxa = INTERVAL1 + INTERVAL2;
  1555. X
  1556. X nextmenu:
  1557. X
  1558. X    no_raw();
  1559. X    gotoxy(0, firstl);
  1560. X    clrpage(firstl);
  1561. X
  1562. X    if (nexta > 0) {
  1563. X    firsta = nexta;
  1564. X    } else
  1565. X    if (purpose[0]) {
  1566. X        msg(purpose);
  1567. X    }
  1568. X
  1569. X    firsta = nexta;
  1570. X    numa = Lines; /* for mark; is set correctly below */
  1571. X    cura = 0;
  1572. X
  1573. X    REDRAW_CHECK;
  1574. X
  1575. X    if (!s_keyboard)
  1576. X    while (nexta < n_articles && cura < maxa) {
  1577. X        REDRAW_CHECK;
  1578. X
  1579. X        articles[firsta+cura]->disp_attr = A_NOT_DISPLAYED;
  1580. X        mark();
  1581. X        nexta++; cura++;
  1582. X    }
  1583. X
  1584. X    fl;
  1585. X    s_keyboard = 0;
  1586. X
  1587. X    prompt_line = firstl + cura;
  1588. X    if (!long_menu || cura < maxa) prompt_line++;
  1589. X
  1590. X    numa = nexta - firsta - 1;
  1591. X     if (numa < 0) prompt_line++;
  1592. X
  1593. X     if (next_cura >= 0) {
  1594. X     cura = next_cura;
  1595. X     next_cura = -1;
  1596. X     } else {
  1597. X     cura = 0;
  1598. X     for (article_id = firsta; cura < numa; article_id++, cura++)
  1599. X         if ((articles[article_id]->attr & A_SELECT) == 0) break;    /*???*/
  1600. X     }
  1601. X
  1602. X  build_prompt:
  1603. X
  1604. X     raw();
  1605. X
  1606. X  Prompt:
  1607. X
  1608. X     prompt(pr_fmt,
  1609. X        pct(0L, (long)(n_articles-1), (long)firsta, (long)(firsta+numa)));
  1610. X
  1611. X     if (delayed_msg[0] != NUL) {
  1612. X     msg(delayed_msg);
  1613. X     delayed_msg[0] = NUL;
  1614. X     }
  1615. X
  1616. X  same_prompt:
  1617. X
  1618. X     if (cura < 0 || cura > numa) cura = 0;
  1619. X
  1620. X     if (numa >= 0) {
  1621. X     gotoxy(0, firstl + cura);
  1622. X     fl; /* place cursor at current article id */
  1623. X     save_xy();
  1624. X     }
  1625. X
  1626. X     last_k_cmd = cur_k_cmd;
  1627. X     k_cmd = get_k_cmd();
  1628. X
  1629. X  alt_key:
  1630. X
  1631. X     switch (cur_k_cmd = k_cmd) {
  1632. X
  1633. X      case K_UNBOUND:
  1634. X     ding();
  1635. X     flush_input();
  1636. X      case K_INVALID:
  1637. X     goto same_prompt;
  1638. X
  1639. X      case K_REDRAW:
  1640. X     next_cura = cura;
  1641. X     goto redraw;
  1642. X
  1643. X      case K_LAST_MESSAGE:
  1644. X     msg((char *)NULL);
  1645. X     goto same_prompt;
  1646. X
  1647. X      case K_HELP:
  1648. X     if (numa < 0)  goto nextmenu;    /* give specific help here */
  1649. X     display_help("menu");
  1650. X     goto redraw;
  1651. X
  1652. X      case K_SHELL:
  1653. X     if (group_file_name) *group_file_name = NUL;
  1654. X     if (shell_escape()) goto redraw;
  1655. X     goto Prompt;
  1656. X
  1657. X      case K_VERSION:
  1658. X     prompt(P_VERSION);
  1659. X     goto same_prompt;
  1660. X
  1661. X      case K_EXTENDED_CMD:
  1662. X     switch (alt_command()) {
  1663. X
  1664. X      case AC_UNCHANGED:
  1665. X         goto same_prompt;
  1666. X
  1667. X      case AC_QUIT:
  1668. X         menu_return( ME_QUIT );
  1669. X
  1670. X      case AC_PROMPT:
  1671. X         goto Prompt;
  1672. X
  1673. X      case AC_REORDER:
  1674. X         firsta = 0;
  1675. X         /* fall thru */
  1676. X      case AC_REDRAW:
  1677. X         goto redraw;
  1678. X
  1679. X      case AC_KEYCMD:
  1680. X         k_cmd = alt_cmd_key;
  1681. X         goto alt_key;
  1682. X
  1683. X      case AC_REENTER_GROUP:
  1684. X         menu_return(ME_REENTER_GROUP);
  1685. X     }
  1686. X
  1687. X      case K_QUIT:
  1688. X     menu_return(ME_QUIT);
  1689. X
  1690. X      case K_CANCEL:
  1691. X     savemode = "Cancel";
  1692. X     fname = "";
  1693. X     goto cancel1;
  1694. X
  1695. X      case K_SAVE_NO_HEADER:
  1696. X      case K_SAVE_SHORT_HEADER:
  1697. X      case K_SAVE_FULL_HEADER:
  1698. X      case K_PRINT:
  1699. X      case K_UNSHAR:
  1700. X      case K_PATCH:
  1701. X      case K_UUDECODE:
  1702. X
  1703. X     if (numa < 0) goto nextmenu;
  1704. X
  1705. X     fname = init_save(k_cmd, &savemode);
  1706. X     if (fname == NULL) goto Prompt;
  1707. X
  1708. X      cancel1:
  1709. X     enable_stop = 0;
  1710. X     save_selected = 0;
  1711. X     doing_unshar = k_cmd == K_UNSHAR || k_cmd == K_PATCH;
  1712. X     did_unshar = 0;
  1713. X
  1714. X     m_startinput();
  1715. X
  1716. X     if (novice)
  1717. X         msg(" * selected articles on this page, + all selected articles");
  1718. X
  1719. X     while (!save_selected && !did_unshar) {
  1720. X         prompt("\1%s\1 %.*s Article (* +): ",
  1721. X            savemode, Columns - 25, fname);
  1722. X
  1723. X         k_cmd = get_k_cmd();
  1724. X
  1725. X         if (k_cmd == K_SELECT_SUBJECT) {
  1726. X         save_selected = 1;
  1727. X         cura = 0;
  1728. X         article_id = firsta;
  1729. X         last_save = firsta + numa;
  1730. X         } else
  1731. X         if (k_cmd == K_AUTO_SELECT) {
  1732. X         save_selected = 2;
  1733. X         cura = -firsta;
  1734. X         article_id = 0;
  1735. X         last_save = n_articles - 1;
  1736. X         } else
  1737. X         if (k_cmd == K_ARTICLE_ID) {
  1738. X         cura = article_id;
  1739. X         article_id += firsta;
  1740. X         last_save = article_id;
  1741. X         } else
  1742. X         break;
  1743. X
  1744. X         for ( ; article_id <= last_save ; article_id++, cura++) {
  1745. X         ah = articles[article_id];
  1746. X         if (save_selected && (ah->attr & A_SELECT) == 0) continue;
  1747. X
  1748. X         if (cur_k_cmd == K_CANCEL) {
  1749. X             if (current_group->group_flag & G_FOLDER) {
  1750. X             if (ah->attr != A_CANCEL) fcancel(ah);
  1751. X             } else
  1752. X             switch (cancel(ah)) {
  1753. X              case -1:
  1754. X                 did_unshar = 1;
  1755. X                 continue;
  1756. X              case 0:
  1757. X                 ah->attr = A_CANCEL;
  1758. X                 break;
  1759. X              default:
  1760. X                 continue;
  1761. X             }
  1762. X
  1763. X             if (!did_unshar)
  1764. X             mark();
  1765. X
  1766. X             continue;
  1767. X         }
  1768. X
  1769. X         if (doing_unshar) {
  1770. X             did_unshar++;
  1771. X         } else
  1772. X         if (ah->subject != NULL)
  1773. X             prompt("Processing '%.50s'...", ah->subject);
  1774. X         else if (cura >= 0 && cura <= numa)
  1775. X             prompt("Processing %c...", ident[cura]);
  1776. X         else
  1777. X             prompt("Processing entry %d...", article_id);
  1778. X
  1779. X         if (save(ah)) {
  1780. X             ah->attr = A_READ;
  1781. X             if (doing_unshar) continue;
  1782. X
  1783. X             if (cura >= 0 && cura <= numa)
  1784. X             mark();
  1785. X         }
  1786. X         }
  1787. X     }
  1788. X
  1789. X     if (save_selected) cura = 0;
  1790. X
  1791. X     m_endinput();
  1792. X
  1793. X     enable_stop = 1;
  1794. X     if (cur_k_cmd != K_CANCEL)
  1795. X         end_save();
  1796. X
  1797. X     if (did_unshar) {
  1798. X         printf("\r\n");
  1799. X         any_key(0);
  1800. X         goto redraw;
  1801. X     }
  1802. X     goto Prompt;
  1803. X
  1804. X      case K_FOLLOW_UP:
  1805. X#ifdef NNTP_POST
  1806. X     if (use_nntp && nntp_no_post()) goto same_prompt;
  1807. X#endif
  1808. X      case K_REPLY:
  1809. X     if (numa < 0) goto nextmenu;
  1810. X
  1811. X     prompt(k_cmd == K_REPLY ?
  1812. X        "\1Reply to author\1 of article: " :
  1813. X        "\1Follow Up\1 to article: ");
  1814. X
  1815. X     if (get_k_cmd() == K_ARTICLE_ID)
  1816. X         if (answer(articles[firsta+article_id], k_cmd, -1))
  1817. X         goto redraw;
  1818. X
  1819. X     goto Prompt;
  1820. X
  1821. X      case K_POST:
  1822. X
  1823. X#ifdef NNTP_POST
  1824. X     if (use_nntp && nntp_no_post())
  1825. X         goto same_prompt;
  1826. X#endif
  1827. X     if (post_menu()) goto redraw;
  1828. X     goto Prompt;
  1829. X
  1830. X      case K_MAIL_OR_FORWARD:
  1831. X     if (numa < 0) goto nextmenu;
  1832. X
  1833. X     prompt("\1Article to be forwarded\1 (SP if none): ");
  1834. X
  1835. X     if ((k_cmd = get_k_cmd()) == K_ARTICLE_ID) {
  1836. X         if (answer(articles[firsta+article_id], K_MAIL_OR_FORWARD, 1))
  1837. X         goto redraw;
  1838. X     } else
  1839. X     if (k_cmd == K_CONTINUE)
  1840. X         if (answer((article_header *)NULL, K_MAIL_OR_FORWARD, 0))
  1841. X         goto redraw;
  1842. X
  1843. X     goto Prompt;
  1844. X/*
  1845. X      case K_CANCEL:
  1846. X     if (numa < 0) goto nextmenu;
  1847. X
  1848. X     if (current_group->group_flag & G_FOLDER) {
  1849. X         prompt("\1Cancel Folder\1 Article: ");
  1850. X         if (get_k_cmd() == K_ARTICLE_ID) {
  1851. X         cura = article_id;
  1852. X         fcancel(articles[firsta+article_id]);
  1853. X         mark();
  1854. X         }
  1855. X         goto Prompt;
  1856. X     }
  1857. X
  1858. X     prompt("\1Cancel\1 Article: ");
  1859. X
  1860. X     if (get_k_cmd() == K_ARTICLE_ID)
  1861. X         if (cancel(articles[firsta+article_id]) & 1) goto redraw;
  1862. X     goto Prompt;
  1863. X*/
  1864. X      case K_UNSUBSCRIBE:
  1865. X     if (unsubscribe(current_group)) {
  1866. X         if (current_group->group_flag & G_UNSUBSCRIBED)
  1867. X         menu_return(ME_NEXT);
  1868. X         home();
  1869. X         CALL(print_header)();
  1870. X     }
  1871. X     goto Prompt;
  1872. X
  1873. X      case K_GROUP_OVERVIEW:
  1874. X     group_overview(-1);
  1875. X     goto redraw;
  1876. X
  1877. X      case K_KILL_HANDLING:
  1878. X     switch (kill_menu((article_header *)NULL)) {
  1879. X      case 0:        /* select */
  1880. X         do_auto_select((regexp *)NULL, 2);
  1881. X         break;
  1882. X      case 1:        /* kill */
  1883. X         if (!do_auto_kill()) break;
  1884. X         goto junk_killed_articles;
  1885. X      default:
  1886. X         break;
  1887. X     }
  1888. X     goto Prompt;
  1889. X
  1890. X      case K_CONTINUE:    /* goto next menu page or show the articles */
  1891. X     repl_attr(firsta, nexta, 0, A_SEEN, 0);
  1892. X     /* fall thru */
  1893. X      case K_CONTINUE_NO_MARK:    /* but don't mark unselected articles */
  1894. X     if (nexta < n_articles) goto nextmenu;
  1895. X     break;
  1896. X
  1897. X      case K_READ_GROUP_UPDATE:
  1898. X     repl_attr_all(0, A_SEEN, 0);
  1899. X     break;
  1900. X
  1901. X      case K_READ_GROUP_THEN_SAME:
  1902. X     break;
  1903. X
  1904. X      case K_NEXT_GROUP_NO_UPDATE:
  1905. X     menu_return(ME_NEXT);
  1906. X
  1907. X      case K_PREVIOUS:
  1908. X     menu_return(ME_PREV);
  1909. X
  1910. X      case K_ADVANCE_GROUP:
  1911. X      case K_BACK_GROUP:
  1912. X     if (merged_menu) {
  1913. X         msg("No possible on merged menu");
  1914. X         goto same_prompt;
  1915. X     }
  1916. X     /* FALL THRU */
  1917. X
  1918. X      case K_GOTO_GROUP:
  1919. X
  1920. X     switch (goto_group(k_cmd, (article_header *)NULL, (flag_type)0)) {
  1921. X
  1922. X      case ME_REDRAW:
  1923. X         firsta = 0;
  1924. X         goto redraw;
  1925. X
  1926. X      case ME_NO_ARTICLES:
  1927. X         msg("No selections made.");
  1928. X
  1929. X      case ME_NO_REDRAW:
  1930. X         goto Prompt;
  1931. X
  1932. X      case ME_QUIT:
  1933. X         menu_return( ME_QUIT );
  1934. X
  1935. X      case ME_PREV:
  1936. X         goto redraw;
  1937. X
  1938. X      case ME_NEXT:
  1939. X         s_keyboard = 1;
  1940. X         goto empty_menu_hack;
  1941. X     }
  1942. X
  1943. X      case K_LEAVE_NEXT:
  1944. X      case K_JUNK_ARTICLES:
  1945. X     junk_prompt = cur_k_cmd == K_JUNK_ARTICLES ? 1 : 5;
  1946. X
  1947. X     for (;;) {
  1948. X         switch (junk_prompt) {
  1949. X          case 1:
  1950. X         if (novice) msg("Use J repeatedly to select other functions");
  1951. X         prompt("\1Mark read\1 S)een U)nmarked A)ll *+)selected a-z . [LN]");
  1952. X         junk_attr = A_READ;
  1953. X         break;
  1954. X          case 2:
  1955. X         prompt("\1Unmark\1 S)een R)ead a-z [*+LAN.J] ");
  1956. X         junk_attr = 0;
  1957. X         break;
  1958. X          case 3:
  1959. X         prompt("\1Select\1 L)eft-over, N(leave-next) [USRa-z.J]");
  1960. X         junk_attr = A_SELECT;
  1961. X         break;
  1962. X          case 4:
  1963. X         prompt("\1Kill\1 R)ead S)een [LANU*+a-z.J]");
  1964. X         junk_attr = A_KILL;
  1965. X         break;
  1966. X          case 5:
  1967. X         prompt("\1Leave\1 a-z .,/ * + U)nmarked [LANRSJ]");
  1968. X         junk_attr = A_LEAVE_NEXT;
  1969. X         break;
  1970. X          default:
  1971. X         junk_prompt = 1;
  1972. X         continue;
  1973. X         }
  1974. X
  1975. X      junk_another:
  1976. X         if (cura < 0 || cura > numa) cura = 0;
  1977. X         gotoxy(0, firstl + cura); fl;
  1978. X         
  1979. X         switch (get_k_cmd()) {
  1980. X          case K_JUNK_ARTICLES:
  1981. X         junk_prompt++;    /* can be 0 */
  1982. X         continue;
  1983. X
  1984. X          case K_ARTICLE_ID:
  1985. X         cura = article_id;
  1986. X          case K_SELECT:
  1987. X         if (junk_attr == A_KILL) junk_attr = A_READ;
  1988. X         articles[firsta + cura]->attr = junk_attr;
  1989. X         mark();
  1990. X         cura++;
  1991. X         goto junk_another;
  1992. X
  1993. X          case K_NEXT_LINE:
  1994. X         cura++;
  1995. X         goto junk_another;
  1996. X         
  1997. X          case K_PREV_LINE:
  1998. X         --cura;
  1999. X         goto junk_another;
  2000. X
  2001. X          case K_SELECT_SUBJECT:
  2002. X         if (junk_attr == A_KILL) junk_attr = A_READ;
  2003. X         repl_attr(firsta, nexta, A_AUTO_SELECT, A_SELECT, 0);
  2004. X         repl_attr(firsta, nexta, A_SELECT, junk_attr, 1);
  2005. X         goto Prompt;
  2006. X
  2007. X          case K_AUTO_SELECT:
  2008. X         repl_attr_all(A_AUTO_SELECT, A_SELECT, 0);
  2009. X         orig_attr = A_SELECT;
  2010. X         break;
  2011. X
  2012. X          default:
  2013. X         switch (cur_key) {
  2014. X          case 'S':
  2015. X             orig_attr = A_SEEN;
  2016. X             break;
  2017. X
  2018. X          case 'U':
  2019. X             orig_attr = 0;
  2020. X             break;
  2021. X
  2022. X          case 'L':
  2023. X             if (junk_attr == A_KILL) junk_attr = A_READ;
  2024. X             orig_attr = A_LEAVE;
  2025. X             break;
  2026. X
  2027. X          case 'A':
  2028. X             orig_attr = A_KILL;
  2029. X             break;
  2030. X
  2031. X          case 'N':
  2032. X             orig_attr = A_LEAVE_NEXT;
  2033. X             break;
  2034. X
  2035. X          case 'R':        /* kill read articles */
  2036. X             orig_attr = A_READ;
  2037. X             break;
  2038. X
  2039. X          default:
  2040. X             goto Prompt;
  2041. X         }
  2042. X         break;
  2043. X         }
  2044. X         break;
  2045. X     }
  2046. X     if (nexta - firsta < n_articles) {
  2047. X         prompt("On all menu pages? ");
  2048. X         switch (yes(1)) {
  2049. X          case -1:
  2050. X         goto Prompt;
  2051. X          case 0:
  2052. X         if (!repl_attr(firsta, nexta, orig_attr, junk_attr, 1))
  2053. X             goto Prompt;
  2054. X         break;
  2055. X          case 1:
  2056. X         if (!repl_attr_all(orig_attr, junk_attr, 1))
  2057. X             goto Prompt;
  2058. X         break;
  2059. X         }
  2060. X     } else
  2061. X         if (!repl_attr(firsta, nexta, orig_attr, junk_attr, 1))
  2062. X         goto Prompt;
  2063. X
  2064. X     if (junk_attr != A_KILL) goto Prompt;
  2065. X
  2066. X      junk_killed_articles:
  2067. X     elim_list[0] = firsta;
  2068. X     elim_list[1] = firsta + cura;
  2069. X     elim_list[2] = nexta;
  2070. X     if (elim_articles(elim_list, 3)) {
  2071. X         firsta = elim_list[0];
  2072. X         goto redraw;
  2073. X     }
  2074. X     firsta = elim_list[0];
  2075. X     cura   = elim_list[1] - firsta;
  2076. X     nexta  = elim_list[2];
  2077. X     goto Prompt;
  2078. X
  2079. X      case K_ARTICLE_ID:
  2080. X     if (numa < 0) goto nextmenu;
  2081. X
  2082. X     if (auto_preview_mode) goto auto_preview;
  2083. X
  2084. X     cura = article_id;
  2085. X     toggle();
  2086. X     mark();
  2087. X     cura++;
  2088. X
  2089. X     goto same_prompt;
  2090. X
  2091. X      case K_SELECT_INVERT:
  2092. X     if (numa < 0) goto nextmenu;
  2093. X
  2094. X     temp = cura;
  2095. X
  2096. X     no_raw();    /* for x-on/x-off */
  2097. X     for (cura = 0; cura <= numa; cura++) {
  2098. X         toggle();
  2099. X         mark();
  2100. X     }
  2101. X     fl;
  2102. X
  2103. X     REDRAW_CHECK;
  2104. X     raw();
  2105. X
  2106. X     cura = temp;
  2107. X     goto same_prompt;
  2108. X
  2109. X
  2110. X      case K_SELECT:
  2111. X     if (numa < 0) goto nextmenu;
  2112. X
  2113. X     toggle();
  2114. X     mark();
  2115. X     cura++;
  2116. X     goto same_prompt;
  2117. X
  2118. X      case K_UNSELECT_ALL:
  2119. X     if (last_k_cmd == K_UNSELECT_ALL)
  2120. X         repl_attr_all(A_SELECT, 0, 1);
  2121. X     else
  2122. X         repl_attr_all(A_AUTO_SELECT, 0, 1);
  2123. X     fl;
  2124. X     cura = 0;
  2125. X     goto same_prompt;
  2126. X
  2127. X      case K_NEXT_LINE:
  2128. X     if (numa < 0) goto nextmenu;
  2129. X
  2130. X     cura++;
  2131. X     goto same_prompt;
  2132. X
  2133. X      case K_PREV_LINE:
  2134. X     if (numa < 0) goto nextmenu;
  2135. X
  2136. X     if (--cura < 0) cura = numa;
  2137. X     goto same_prompt;
  2138. X
  2139. X      case K_SELECT_SUBJECT:
  2140. X     if (numa < 0) goto nextmenu;
  2141. X
  2142. X     if (last_k_cmd != K_ARTICLE_ID && last_k_cmd != K_SELECT)
  2143. X         toggle();
  2144. X
  2145. X     while (firsta+cura > 0 &&
  2146. X        (articles[firsta+cura]->flag & (A_SAME | A_ALMOST_SAME)))
  2147. X         cura--;
  2148. X
  2149. X     do {
  2150. X         new_mark(last_attr);
  2151. X         cura++;
  2152. X         if (firsta+cura >= n_articles) break;
  2153. X     } while (articles[firsta+cura]->flag & (A_SAME | A_ALMOST_SAME));
  2154. X
  2155. X     goto same_prompt;
  2156. X
  2157. X      case K_SELECT_RANGE:
  2158. X     if (numa < 0) goto nextmenu;
  2159. X
  2160. X     if (last_k_cmd == K_ARTICLE_ID || last_k_cmd == K_SELECT) {
  2161. X         cura--;
  2162. X         if (cura < 0) cura = numa;
  2163. X     } else
  2164. X         last_attr = (articles[firsta+cura]->attr & A_SELECT) ? 0 : A_SELECT;
  2165. X
  2166. X      range_again:
  2167. X
  2168. X     prompt("\1%select range\1 %c-", last_attr ? "S" : "Des", ident[cura]);
  2169. X
  2170. X     k_cmd = get_k_cmd();
  2171. X     if (k_cmd == K_SELECT_RANGE) {
  2172. X         last_attr = last_attr ? 0 : A_SELECT;
  2173. X         goto range_again;
  2174. X     }
  2175. X
  2176. X     if (k_cmd != K_ARTICLE_ID) goto Prompt;
  2177. X
  2178. X     if (last_k_cmd != K_ARTICLE_ID && last_k_cmd != K_SELECT)
  2179. X         new_mark(last_attr);
  2180. X
  2181. X     if (article_id <= cura) {
  2182. X         while (cura >= article_id) {
  2183. X         new_mark(last_attr);
  2184. X         cura--;
  2185. X         }
  2186. X         if (cura < 0) cura = 0;
  2187. X     } else {
  2188. X         while (cura <= article_id) {
  2189. X         new_mark(last_attr);
  2190. X         cura++;
  2191. X         }
  2192. X         if (cura > numa) cura = numa;
  2193. X     }
  2194. X     goto Prompt;
  2195. X
  2196. X      case K_AUTO_SELECT:
  2197. X     do_auto_select((regexp *)NULL, 1);
  2198. X     goto same_prompt;
  2199. X
  2200. X     case K_GOTO_MATCH:
  2201. X     prompt("\1Select regexp\1 ");
  2202. X     if ((fname = get_s(NONE, NONE, NONE, NULL_FCT)) == NULL)
  2203. X         goto Prompt;
  2204. X
  2205. X     if (*fname != NUL) {
  2206. X         if (regular_expr) freeobj(regular_expr);
  2207. X         if (case_fold_search) fold_string(fname);
  2208. X         regular_expr = regcomp(fname);
  2209. X     }
  2210. X
  2211. X     if (regular_expr == NULL)
  2212. X         msg("No previous expression");
  2213. X     else
  2214. X         do_auto_select(regular_expr, 2);
  2215. X
  2216. X     goto Prompt;
  2217. X
  2218. X      case K_NEXT_PAGE:
  2219. X     if (nexta < n_articles) goto nextmenu;
  2220. X     if (firsta == 0) goto same_prompt;
  2221. X
  2222. X     nexta = 0;
  2223. X     goto nextmenu;
  2224. X
  2225. X      case K_PREV_PAGE:
  2226. X     if (firsta == 0 && nexta == n_articles) goto same_prompt;
  2227. X
  2228. X     nexta = (firsta > 0 ? firsta : n_articles) - maxa;
  2229. X     if (nexta <= 1) nexta = 0;
  2230. X     goto nextmenu;
  2231. X
  2232. X      case K_FIRST_PAGE:
  2233. X     if (firsta == 0) goto same_prompt;
  2234. X
  2235. X     nexta = 0;
  2236. X     goto nextmenu;
  2237. X
  2238. X      case K_LAST_PAGE:
  2239. X     if (nexta == n_articles) goto same_prompt;
  2240. X
  2241. X     nexta = n_articles - maxa;
  2242. X     if (nexta <= 1) nexta = 0;
  2243. X     goto nextmenu;
  2244. X
  2245. X      case K_PREVIEW:
  2246. X     if (numa < 0) goto nextmenu;
  2247. X
  2248. X      preview_other:
  2249. X
  2250. X     prompt("\1Preview article\1");
  2251. X     k_cmd = get_k_cmd();
  2252. X
  2253. X     if (k_cmd != K_ARTICLE_ID) {
  2254. X         if (k_cmd != K_PREVIEW)
  2255. X         goto Prompt;
  2256. X         article_id = cura;
  2257. X     }
  2258. X
  2259. X      auto_preview:
  2260. X     temp = prompt_line;
  2261. X
  2262. X      preview_next:
  2263. X     cura = article_id;
  2264. X     ah = articles[firsta+cura];
  2265. X
  2266. X     no_raw();
  2267. X     ah->attr = 0;
  2268. X     menu_cmd = more(ah, MM_PREVIEW, prompt_line);
  2269. X     if (menu_cmd == MC_MENU) {
  2270. X         next_cura = cura;
  2271. X         if (prompt_line < 0) goto redraw;
  2272. X         mark();
  2273. X         prompt_line = temp;
  2274. X         goto build_prompt;
  2275. X     }
  2276. X
  2277. X     if (preview_mark_read && ah->attr == 0) ah->attr = A_READ;
  2278. X     if (prompt_line >= 0)
  2279. X         mark();
  2280. X     next_cura = ++cura;
  2281. X
  2282. X     switch (menu_cmd) {
  2283. X
  2284. X      case MC_DO_KILL:
  2285. X         if (!do_auto_kill()) break;
  2286. X         elim_list[0] = firsta;
  2287. X         elim_list[1] = firsta + cura;
  2288. X         elim_articles(elim_list, 2);
  2289. X         firsta = elim_list[0];
  2290. X         next_cura = elim_list[1] - firsta;
  2291. X         goto redraw;
  2292. X
  2293. X      case MC_DO_SELECT:
  2294. X         if (prompt_line >= 0) { /* not redrawn */
  2295. X         do_auto_select((regexp *)NULL, 2);
  2296. X         break;
  2297. X         }
  2298. X         numa = -1;
  2299. X         do_auto_select((regexp *)NULL, 2);
  2300. X         /* FALL THRU */
  2301. X
  2302. X      case MC_QUIT:
  2303. X         menu_return( ME_QUIT );
  2304. X
  2305. X      case MC_REENTER_GROUP:
  2306. X         menu_return( ME_REENTER_GROUP );
  2307. X
  2308. X      case MC_NEXT:
  2309. X      case MC_PREVIEW_NEXT:
  2310. X         if (prompt_line < 0) {    /* redrawn screen ! */
  2311. X         if (quit_preview(menu_cmd)) goto redraw;
  2312. X         prompt_line = Lines;
  2313. X         } else {
  2314. X/*         if (ah->attr == A_LEAVE || ah->attr == A_LEAVE_NEXT) {
  2315. X             cura--;
  2316. X             mark();
  2317. X             cura++;
  2318. X         }
  2319. X*/         if (quit_preview(menu_cmd)) break;
  2320. X         prompt_line = temp;
  2321. X         }
  2322. X         article_id = cura;
  2323. X         goto preview_next;
  2324. X
  2325. X      case MC_PREVIEW_OTHER:
  2326. X         prompt_line = temp;
  2327. X         raw();
  2328. X         goto preview_other;
  2329. X
  2330. X      default:
  2331. X         if (prompt_line < 0) goto redraw;
  2332. X         break;
  2333. X     }
  2334. X
  2335. X     prompt_line = temp;
  2336. X     goto build_prompt;
  2337. X
  2338. X      case K_LAYOUT:
  2339. X     if (++fmt_linenum > 4) fmt_linenum = 0;
  2340. X     goto redraw;
  2341. X
  2342. X      default:
  2343. X     msg("Command %d not supported", k_cmd);
  2344. X     goto same_prompt;
  2345. X     }
  2346. X
  2347. X    no_raw();
  2348. X
  2349. X    switch (show_articles()) {
  2350. X
  2351. X     case MC_MENU:
  2352. X    goto redraw;
  2353. X
  2354. X     case MC_READGROUP:
  2355. X    if (k_cmd == K_READ_GROUP_THEN_SAME || also_read_articles) goto redraw;
  2356. X     case MC_NEXTGROUP:
  2357. X    menu_cmd = ME_NEXT;
  2358. X    break;
  2359. X
  2360. X     case MC_REENTER_GROUP:
  2361. X    menu_cmd = ME_REENTER_GROUP;
  2362. X    break;
  2363. X
  2364. X     case MC_QUIT:
  2365. X    menu_cmd = ME_QUIT;
  2366. X    break;
  2367. X
  2368. X     default:
  2369. X    sys_error("show_articles returned improper value");
  2370. X    }
  2371. X
  2372. X menu_exit:
  2373. X
  2374. X    firsta = o_firsta;
  2375. X    in_menu_mode = o_mode;
  2376. X    menu_level--;
  2377. X
  2378. X    no_raw();
  2379. X    return menu_cmd;
  2380. X}
  2381. X
  2382. X
  2383. X/*
  2384. X *    return article header for article on menu
  2385. X */
  2386. X
  2387. Xarticle_header *get_menu_article()
  2388. X{
  2389. X    register article_header *ah;
  2390. X
  2391. X    fputs(" from article: ", stdout); fl;
  2392. X
  2393. X    if (get_k_cmd() == K_ARTICLE_ID) {
  2394. X    ah = articles[firsta + article_id];
  2395. X    if (ah->a_group) init_group(ah->a_group);
  2396. X    return ah;
  2397. X    }
  2398. X
  2399. X    return NULL;
  2400. X}
  2401. X
  2402. X
  2403. X
  2404. X/*
  2405. X *    read command from command line
  2406. X */
  2407. X
  2408. Xalt_command()
  2409. X{
  2410. X    int ok_val, macro_cmd;
  2411. X    char *cmd, brkchars[10];
  2412. X    extern key_type erase_key;
  2413. X    extern int get_from_macro;
  2414. X    extern int alt_completion();
  2415. X
  2416. X    if (get_from_macro)
  2417. X    ok_val = AC_UNCHANGED;
  2418. X    else {
  2419. X    prompt(":");
  2420. X    ok_val = AC_PROMPT;
  2421. X    }
  2422. X
  2423. X again:
  2424. X
  2425. X    sprintf(brkchars, "?%c ", erase_key);
  2426. X
  2427. X    cmd = get_s(NONE, NONE, brkchars, alt_completion);
  2428. X    if (cmd == NULL ||
  2429. X    *cmd == NUL || *cmd == SP || *cmd == erase_key)
  2430. X    return ok_val;
  2431. X
  2432. X    macro_cmd = get_from_macro;
  2433. X
  2434. X    if (*cmd == '?') {
  2435. X    display_file("help.extended", CLEAR_DISPLAY);
  2436. X    ok_val = AC_REDRAW;
  2437. X    goto new_prompt;
  2438. X    }
  2439. X
  2440. X    ok_val = parse_command(cmd, ok_val, (FILE *)NULL);
  2441. X    if (ok_val != AC_REDRAW || !delay_redraw) return ok_val;
  2442. X
  2443. X new_prompt:
  2444. X    if (macro_cmd) return ok_val;
  2445. X
  2446. X    prompt_line = -1;
  2447. X    printf("\n\r:");
  2448. X    fl;
  2449. X    goto again;
  2450. X}
  2451. END_OF_FILE
  2452.   if test 33007 -ne `wc -c <'menu.c'`; then
  2453.     echo shar: \"'menu.c'\" unpacked with wrong size!
  2454.   fi
  2455.   # end of 'menu.c'
  2456. fi
  2457. echo shar: End of archive 6 \(of 22\).
  2458. cp /dev/null ark6isdone
  2459. MISSING=""
  2460. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
  2461.     if test ! -f ark${I}isdone ; then
  2462.     MISSING="${MISSING} ${I}"
  2463.     fi
  2464. done
  2465. if test "${MISSING}" = "" ; then
  2466.     echo You have unpacked all 22 archives.
  2467.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2468. else
  2469.     echo You still must unpack the following archives:
  2470.     echo "        " ${MISSING}
  2471. fi
  2472. exit 0
  2473.  
  2474. exit 0 # Just in case...
  2475.